package com.common.base.widget

import android.content.Context
import android.content.res.TypedArray
import android.graphics.*
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.os.Build
import android.util.AttributeSet
import android.widget.FrameLayout
import com.common.base.R
import com.common.base.app.extras.dp2px
import com.common.base.utils.AppUtils.getColor

/**
 * github地址：https://github.com/dmytrodanylyk/shadow-layout
 * 添加阴影效果的控件
 * 由于第三库此控件没有及时回收bitmap，存在内存泄漏问题
 * 这里直接下载源码改动
 */
class ShadowLayout : FrameLayout {
    private var mShadowColor = 0
    private var mShadowRadius = 0f
    private var mCornerRadius = 0f
    private var mDx = 0f
    private var mDy = 0f
    private var mInvalidateShadowOnSizeChanged = true
    private var mForceInvalidateShadow = false
    private var mBitmap: Bitmap? = null
    private var outputBitmap: Bitmap? = null

    constructor(context: Context) : super(context) {
        initView(context, null)
    }

    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
        initView(context, attrs)
    }

    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ) {
        initView(context, attrs)
    }

    override fun getSuggestedMinimumWidth(): Int {
        return 0
    }

    override fun getSuggestedMinimumHeight(): Int {
        return 0
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        if (w > 0 && h > 0 && (background == null || mInvalidateShadowOnSizeChanged || mForceInvalidateShadow)) {
            mForceInvalidateShadow = false
            setBackgroundCompat(w, h)
        }
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        if (mForceInvalidateShadow) {
            mForceInvalidateShadow = false
            setBackgroundCompat(right - left, bottom - top)
        }
    }

    fun setInvalidateShadowOnSizeChanged(invalidateShadowOnSizeChanged: Boolean) {
        mInvalidateShadowOnSizeChanged = invalidateShadowOnSizeChanged
    }

    fun invalidateShadow() {
        mForceInvalidateShadow = true
        requestLayout()
        invalidate()
    }

    private fun initView(context: Context, attrs: AttributeSet?) {
        initAttributes(context, attrs)
        val xPadding = (mShadowRadius + Math.abs(mDx)).toInt()
        val yPadding = (mShadowRadius + Math.abs(mDy)).toInt()
        setPadding(xPadding, yPadding, xPadding, yPadding)
    }

    //***********************修改********************************
    //添加bitmap的回收处理 避免创建过的bitmap没有进行回收
    private fun setBackgroundCompat(w: Int, h: Int) {
        try {
            recycleBitmap()
            mBitmap = createShadowBitmap(
                w,
                h,
                mCornerRadius,
                mShadowRadius,
                mDx,
                mDy,
                mShadowColor,
                Color.TRANSPARENT
            )
            val drawable = BitmapDrawable(resources, mBitmap)
            setDrawable(drawable)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    private fun initAttributes(context: Context, attrs: AttributeSet?) {
        val attr = getTypedArray(context, attrs, R.styleable.ShadowLayout)
        try {
            mCornerRadius = attr.getDimension(R.styleable.ShadowLayout_sl_cornerRadius, dp2px(4f))
            mShadowRadius = attr.getDimension(R.styleable.ShadowLayout_sl_shadowRadius, dp2px(4f))
            mDx = attr.getDimension(R.styleable.ShadowLayout_sl_dx, 0f)
            mDy = attr.getDimension(R.styleable.ShadowLayout_sl_dy, 0f)
            mShadowColor = attr.getColor(
                R.styleable.ShadowLayout_sl_shadowColor,
                resources.getColor(R.color.default_shadow_color)
            )
        } finally {
            attr.recycle()
        }
    }

    private fun getTypedArray(
        context: Context,
        attributeSet: AttributeSet?,
        attr: IntArray
    ): TypedArray {
        return context.obtainStyledAttributes(attributeSet, attr, 0, 0)
    }

    private fun createShadowBitmap(
        shadowWidth: Int, shadowHeight: Int, cornerRadius: Float, shadowRadius: Float,
        dx: Float, dy: Float, shadowColor: Int, fillColor: Int
    ): Bitmap? {
        try {
            recycleOutputBitmap()
            outputBitmap = Bitmap.createBitmap(shadowWidth, shadowHeight, Bitmap.Config.ALPHA_8)
            var canvas: Canvas? = null
            outputBitmap?.let { canvas = Canvas(it) }

            val shadowRect = RectF(
                shadowRadius,
                shadowRadius,
                shadowWidth - shadowRadius,
                shadowHeight - shadowRadius
            )
            if (dy > 0) {
                shadowRect.top += dy
                shadowRect.bottom -= dy
            } else if (dy < 0) {
                shadowRect.top += Math.abs(dy)
                shadowRect.bottom -= Math.abs(dy)
            }
            if (dx > 0) {
                shadowRect.left += dx
                shadowRect.right -= dx
            } else if (dx < 0) {
                shadowRect.left += Math.abs(dx)
                shadowRect.right -= Math.abs(dx)
            }
            val shadowPaint = Paint()
            shadowPaint.isAntiAlias = true
            shadowPaint.color = fillColor
            shadowPaint.style = Paint.Style.FILL
            if (!isInEditMode) {
                shadowPaint.setShadowLayer(shadowRadius, dx, dy, shadowColor)
            }
            canvas?.drawRoundRect(shadowRect, cornerRadius, cornerRadius, shadowPaint)
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return outputBitmap
    }

    //*******************************新增方法****************************************************
    private fun setDrawable(drawable: Drawable?) {
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
            super.setBackgroundDrawable(drawable)
        } else {
            super.setBackground(drawable)
        }
    }

    fun setShadowColorId(colorId: Int) {
        mShadowColor = getColor(colorId)
        invalidateShadow()
    }

    fun setShadowColor(color: Int) {
        mShadowColor = color
        invalidateShadow()
    }

    private fun recycleBitmap() {
        if (mBitmap != null && !mBitmap!!.isRecycled) {
            setDrawable(null)
            mBitmap?.recycle()
            mBitmap = null
        }
    }

    private fun recycleOutputBitmap() {
        if (outputBitmap != null && !outputBitmap!!.isRecycled) {
            outputBitmap?.recycle()
            outputBitmap = null
        }
    }

    /**
     * 控件销毁时添加回收bitmap处理
     */
    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        recycleBitmap()
    }
}